package cfg.mpsc;
import java.util.ArrayList;
import java.util.List;


public class PathProcessor {
	
	private List<Path> paths = new ArrayList<Path>();
	private INode begin;
	
	public PathProcessor(INode begin){
		this.begin = begin;
	}
	
	
	public List<Path> process(){
		List<Path> doing = new ArrayList<Path>();
		doing.add(new Path(begin));
		while(!doing.isEmpty()){
			List<Path> toAdd = new ArrayList<Path>();
			List<Path> doneProcessing = new ArrayList<Path>();
			for(int i=0;i<doing.size();++i){
				Path processing = doing.get(i);
				INode point = processing.lastNode();
				switch(point.nextNodes().size()){
				case 0:
					//this is a final node!
					// remove this path from doing list
					doneProcessing.add(processing);
					break;
				case 1:
					//there is no choice, add this node
					processing.add(point.nextNodes().get(0));	
					break;
				case 2:
					//it can be either a loop, either a condition 
					int index0 = processing.lastIndexOf(point.nextNodes().get(0));
					int index1 = processing.lastIndexOf(point.nextNodes().get(1));
					if(index0 == index1 && index0 == -1){ //none of the nodes exists in path
						Path newPath = processing.clone();
						processing.add(point.nextNodes().get(0));
						newPath.add(point.nextNodes().get(1));
						toAdd.add(newPath);
					} else {//one (or both) of the nodes already exists in path -> loop
						if(index0>=0 && index1 >=0 ){ //both nodes exists in path
							throw new RuntimeException("Error: Both nodes in loop.");
						} else if(index0>=0){ // node 0 already exists, add just node 1
							processing.add(point.nextNodes().get(1));
						} else{ //node 1 already exists, add just node 0
							processing.add(point.nextNodes().get(0));
						}
					}
					break;
				default:
					throw new RuntimeException("Node should not have more than two next nodes");
				}
			}
			//process pending actions
			doing.removeAll(doneProcessing);
			doing.addAll(toAdd);
			paths.addAll(doneProcessing);
		}
		return paths;
	}
	

}
